package com.qdaily.supportlibrary.pulltorefresh.header;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import com.qdaily.supportlibrary.pulltorefresh.PtrFrameLayout;
import com.qdaily.supportlibrary.pulltorefresh.PtrUIHandler;
import com.qdaily.supportlibrary.pulltorefresh.PtrUIHandlerHook;

public class MaterialHeader extends View implements PtrUIHandler {

    private MaterialProgressDrawable mDrawable;
    private float mScale = 1f;
    private PtrFrameLayout mPtrFrameLayout;

    private Animation mScaleAnimation = new Animation() {
        @Override
        public void applyTransformation(float interpolatedTime, Transformation t) {
            mScale = 1f - interpolatedTime;
            mDrawable.setAlpha( (int) (255 * mScale) );
            invalidate();
        }
    };

    public MaterialHeader(Context context) {
        super( context );
        initView();
    }

    public MaterialHeader(Context context, AttributeSet attrs) {
        super( context, attrs );
        initView();
    }

    public MaterialHeader(Context context, AttributeSet attrs, int defStyleAttr) {
        super( context, attrs, defStyleAttr );
        initView();
    }

    public void setPtrFrameLayout(PtrFrameLayout layout) {

        final PtrUIHandlerHook mPtrUIHandlerHook = new PtrUIHandlerHook() {
            @Override
            public void run() {
                startAnimation( mScaleAnimation );
            }
        };

        mScaleAnimation.setDuration( 200 );
        mScaleAnimation.setAnimationListener( new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                mPtrUIHandlerHook.resume();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        } );

        mPtrFrameLayout = layout;
        mPtrFrameLayout.setRefreshCompleteHook( mPtrUIHandlerHook );
    }

    private void initView() {
        mDrawable = new MaterialProgressDrawable( getContext(), this );
        mDrawable.setBackgroundColor( Color.WHITE );
        mDrawable.setCallback( this );
    }

    @Override
    public void invalidateDrawable(Drawable dr) {
        if (dr == mDrawable) {
            invalidate();
        } else {
            super.invalidateDrawable( dr );
        }
    }

    public void setColorSchemeColors(int[] colors) {
        mDrawable.setColorSchemeColors( colors );
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = mDrawable.getIntrinsicHeight() + getPaddingTop() + getPaddingBottom();
        heightMeasureSpec = MeasureSpec.makeMeasureSpec( height, MeasureSpec.EXACTLY );
        super.onMeasure( widthMeasureSpec, heightMeasureSpec );
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int size = mDrawable.getIntrinsicHeight();
        mDrawable.setBounds( 0, 0, size, size );
    }

    @Override
    protected void onDraw(Canvas canvas) {
        final int saveCount = canvas.save();
        Rect rect = mDrawable.getBounds();
        int l = getPaddingLeft() + (getMeasuredWidth() - mDrawable.getIntrinsicWidth()) / 2;
        canvas.translate( l, getPaddingTop() );
        canvas.scale( mScale, mScale, rect.exactCenterX(), rect.exactCenterY() );
        mDrawable.draw( canvas );
        canvas.restoreToCount( saveCount );
    }

    /**
     * When the content view has reached top and refresh has been completed,
     * view will be reset.
     *
     * @param frame
     */
    @Override
    public void onUIReset(PtrFrameLayout frame) {
        mScale = 1f;
        mDrawable.stop();
    }

    /**
     * prepare for loading
     *
     * @param frame
     */
    @Override
    public void onUIRefreshPrepare(PtrFrameLayout frame) {
    }

    /**
     * perform refreshing UI
     *
     * @param frame
     */
    @Override
    public void onUIRefreshBegin(PtrFrameLayout frame) {
        mDrawable.setAlpha( 255 );
        mDrawable.start();
    }

    /**
     * perform UI after refresh
     *
     * @param frame
     */
    @Override
    public void onUIRefreshComplete(PtrFrameLayout frame) {
        mDrawable.stop();
    }

    @Override
    public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, int oldPosition, int currentPosition,
                                   float oldPercent, float currentPercent) {
        float percent = Math.min( 1f, currentPercent );

        if (status == PtrFrameLayout.PTR_STATUS_PREPARE) {
            mDrawable.setAlpha( (int) (255 * percent) );
            mDrawable.showArrow( true );

            float strokeStart = ((percent) * .8f);
            mDrawable.setStartEndTrim( 0f, Math.min( 0.8f, strokeStart ) );
            mDrawable.setArrowScale( Math.min( 1f, percent ) );

            // magic
            float rotation = (-0.25f + .4f * percent + percent * 2) * .5f;
            mDrawable.setProgressRotation( rotation );
            invalidate();
        }
    }
}
